package com.ocean.courtyard.core.datasource.config;

import com.ocean.courtyard.constants.ConstantsAttribute;
import com.ocean.courtyard.core.datasource.SqlSessionImpl;
import lombok.Getter;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.plugin.java.JavaPlugin;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Properties;

public class MyBatisConfig {

    @Getter
    private SqlSessionFactory sqlSessionFactory;

    @Getter
    private SqlSessionImpl sqlSessionImpl;

    public MyBatisConfig(JavaPlugin plugin) {
        init(plugin);
    }

    private void init(JavaPlugin plugin) {
        FileConfiguration config = plugin.getConfig();
        try {
            String hostname = config.getString(ConstantsAttribute.HOSTNAME);
            int port = config.getInt(ConstantsAttribute.PORT);
            String database = config.getString(ConstantsAttribute.DATABASE);
            String username = config.getString(ConstantsAttribute.USERNAME);
            String password = config.getString(ConstantsAttribute.PASSWORD);
            String parameters = config.getString(ConstantsAttribute.PARAMETERS);

            String maximumPoolSize = config.getString(ConstantsAttribute.MAXIMUM_POOL_SIZE);
            int minimumIdle = config.getInt(ConstantsAttribute.MINIMUM_IDLE);
            int idleTimeout = config.getInt(ConstantsAttribute.IDLE_TIMEOUT);
            long maxLifetime = config.getLong(ConstantsAttribute.MAX_LIFETIME);
            long connectionTimeout = config.getLong(ConstantsAttribute.CONNECTION_TIMEOUT);

            if (hostname != null && database != null && username != null && password != null && parameters != null && maximumPoolSize != null) {
                Properties properties = new Properties();
                properties.setProperty("db.hostname", hostname);
                properties.setProperty("db.port", String.valueOf(port));
                properties.setProperty("db.database", database);
                properties.setProperty("db.username", username);
                properties.setProperty("db.password", password);
                properties.setProperty("db.parameters", parameters);
                properties.setProperty("pool.maximumPoolSize", maximumPoolSize);
                properties.setProperty("pool.minimumIdle", String.valueOf(minimumIdle));
                properties.setProperty("pool.idleTimeout", String.valueOf(idleTimeout));
                properties.setProperty("pool.maxLifetime", String.valueOf(maxLifetime));
                properties.setProperty("pool.connectionTimeout", String.valueOf(connectionTimeout));

                try (InputStream is = new ByteArrayInputStream(readMyBatisConfigTemplate().getBytes())) {
                    sqlSessionFactory = new SqlSessionFactoryBuilder().build(is, properties);
                    createTables();
                }
            } else {
                plugin.getLogger().warning("MyBatis configuration file does not contain hostname and port");
            }
        } catch (Exception e) {
            plugin.getLogger().warning("Connection Database error..." + e.fillInStackTrace());
        }
    }

    private String readMyBatisConfigTemplate() throws IOException {
        try (InputStream is = Resources.getResourceAsStream("mybatis-config.xml")) {
            if (is == null) {
                throw new IOException("The mybatis-config.xml file was not found.");
            }
            return new String(is.readAllBytes(), StandardCharsets.UTF_8);
        }
    }

    private void createTables() {
        SqlSessionImpl sqlSession = new SqlSessionImpl(sqlSessionFactory);
        this.sqlSessionImpl = sqlSession;
        sqlSession.initialize();
    }
}
